﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Printing;
using System.Drawing;

using MessagingToolkit.QRCode.Codec;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;
using ESF.General;
using Zen.Barcode;

#endregion


namespace ESF.WinForms.ScannerControls
{
	public class StickerPrintPage : PrintDocument
	{
		#region Constantes

		public const double HUNDREDOFINCHES_FACTOR = 3.937;

		#endregion


		#region Propiedades

		public int PageCount
		{
			get 
			{
				return (int) Math.Ceiling (_StickerData.Count * 1.0 / StickerPageSettings.StickerByPage);
			}
		}

		#endregion


		#region Miembros

		public StickerPageSettings StickerPageSettings;

		private List<KeyValuePair<string,string>> _StickerData;

		private BarcodeType _BarcodeType;

		public BarcodeType BarcodeType
		{
			set
			{
				_BarcodeType = value;


				switch (value)
				{
					case BarcodeType.Code128:
						_BarcodeDrawer = BarcodeDrawFactory.GetSymbology (BarcodeSymbology.Code128);
					break;

					case BarcodeType.Code39:
						_BarcodeDrawer = BarcodeDrawFactory.GetSymbology (BarcodeSymbology.Code39NC);
					break;

					case BarcodeType.EAN:
						_BarcodeDrawer = BarcodeDrawFactory.GetSymbology (BarcodeSymbology.CodeEan13);
					break;

					case BarcodeType.QR:
						_QRCodeEncoder = new QRCodeEncoder ();
						_QRCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
						_QRCodeEncoder.QRCodeScale = 2;
						_QRCodeEncoder.QRCodeVersion = 3;
						_QRCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
					break;

					default:
						throw new NotSupportedException (string.Format ("The barcode type {0} is not supported for printing", _BarcodeType));
				}
			}
			get
			{
				return _BarcodeType;
			}
		}




		private Font _LabelFont;

		private BarcodeDraw _BarcodeDrawer;

		private QRCodeEncoder _QRCodeEncoder;

		private int _CurrentPrintIndexItem;

		#endregion


		#region Constructor

		public StickerPrintPage (PrinterSettings pPrinterSettings)
		{
			DocumentName = "BarCode(s) Page";

			DefaultPageSettings = new PageSettings (pPrinterSettings);
			
			_StickerData = new List<KeyValuePair<string,string>> ();
			
			#region Asignacion de Fuentes

			_LabelFont = new Font ("Arial", 8, FontStyle.Regular); 
			
			#endregion
		}


		#endregion


		#region Funciones

		public void AddSticker (string pLabel, string pContent)
		{
			if (pLabel.Length * 2 > StickerPageSettings.StickerWidth_mm)
			{
				pLabel = pLabel.Substring (0, (int) Math.Ceiling (StickerPageSettings.StickerWidth_mm / 2));
			}

			_StickerData.Add (new KeyValuePair<string,string> (pLabel, pContent));
		}


		public void ClearStickers ()
		{
			_StickerData.Clear ();
		}

		#endregion


		#region Funciones de Impresion

		protected override void OnBeginPrint(PrintEventArgs e)
		{
			base.OnBeginPrint(e);

			_CurrentPrintIndexItem = 0;

			// 1 millimeter = 0.0393700787 inches
			// PaperSize esta en cientos de pulgada
			
			DefaultPageSettings.Margins = new Margins (0, 0, 0, 0);

			//DefaultPageSettings.Landscape = false;
			
			DefaultPageSettings.Color = false;

			DefaultPageSettings.PaperSize = new PaperSize ();

			DefaultPageSettings.PaperSize.Width = 
				(int) Math.Ceiling (
					// Cantidad de rotulos
					StickerPageSettings.StickerByRow * 
					// Ancho ocupado por los rotulos
					(StickerPageSettings.StickerWidth_mm + (2 * StickerPageSettings.StickerHorizontalSeparator_mm)) * HUNDREDOFINCHES_FACTOR);
			
			
			if (_StickerData.Count > StickerPageSettings.StickerByPage)
			{
				DefaultPageSettings.PaperSize.Height = 			
					(int) Math.Ceiling (
						// Cantidad de rotulos
						(StickerPageSettings.StickerByPage / StickerPageSettings.StickerByRow) *
							// Espacio ocupado por los rotulos
							(StickerPageSettings.StickerHeight_mm + (2 * StickerPageSettings.StickerVerticalSeparator_mm)) * HUNDREDOFINCHES_FACTOR);
			}
			else
			{
				DefaultPageSettings.PaperSize.Height = 			
					(int) Math.Ceiling (
						// Cantidad de rotulos
						Math.Ceiling (_StickerData.Count * 1.0 / StickerPageSettings.StickerByRow) *
							// Espacio ocupado por los rotulos
							(StickerPageSettings.StickerHeight_mm + (2 * StickerPageSettings.StickerVerticalSeparator_mm)) * HUNDREDOFINCHES_FACTOR);
			}
		}


		protected override void OnPrintPage(PrintPageEventArgs e)
		{
			float xIndex;
			float yIndex;


			base.OnPrintPage(e);
			
			
			yIndex = (float) (e.MarginBounds.Top + StickerPageSettings.StickerHorizontalSeparator_mm * HUNDREDOFINCHES_FACTOR);

			for (int rowIndex = 0; rowIndex < StickerPageSettings.StickerByPage / StickerPageSettings.StickerByRow; rowIndex ++)
			{
				xIndex = (float) (e.MarginBounds.Left + (StickerPageSettings.StickerHorizontalSeparator_mm * HUNDREDOFINCHES_FACTOR)); 

				for (int colIndex = 0; colIndex < StickerPageSettings.StickerByRow; colIndex ++)
				{
					if (StickerPageSettings.StickerIncludeBorders)
					{
						e.Graphics.DrawRectangle (Pens.Gray,
							xIndex, 
							yIndex, 
							(float) ((StickerPageSettings.StickerWidth_mm - 3) * HUNDREDOFINCHES_FACTOR), 
							(float) ((StickerPageSettings.StickerHeight_mm) * HUNDREDOFINCHES_FACTOR));
					}

					if (_StickerData.Count > _CurrentPrintIndexItem)
					{
						switch (BarcodeType)
						{
							case BarcodeType.Code128:
								e.Graphics.DrawString (_StickerData [_CurrentPrintIndexItem].Key.Replace (Environment.NewLine, " - "), _LabelFont, Brushes.Black, xIndex + 5, yIndex + 4);
								e.Graphics.DrawImage (ImageHelper.GenerateTumbnail (_BarcodeDrawer.Draw (_StickerData [_CurrentPrintIndexItem].Value, 28, 1), 1.25), xIndex + 5, yIndex + 20);	
								break;

							default:
								e.Graphics.DrawString (_StickerData [_CurrentPrintIndexItem].Key, _LabelFont, Brushes.Black, xIndex + 76, yIndex + 7);
								e.Graphics.DrawImage ((Image) _QRCodeEncoder.Encode (_StickerData [_CurrentPrintIndexItem].Value, Encoding.ASCII), xIndex + 8, yIndex + 4);
								break;
						}
											
						_CurrentPrintIndexItem ++;
					}

					xIndex += (float) (2 * StickerPageSettings.StickerHorizontalSeparator_mm * HUNDREDOFINCHES_FACTOR) + (float) (StickerPageSettings.StickerWidth_mm * HUNDREDOFINCHES_FACTOR);
				}

				yIndex += (float) (2 * StickerPageSettings.StickerHorizontalSeparator_mm * HUNDREDOFINCHES_FACTOR) + (float) (StickerPageSettings.StickerHeight_mm * HUNDREDOFINCHES_FACTOR);
			}

			e.HasMorePages = (_StickerData.Count - 1 > _CurrentPrintIndexItem);
		}

		#endregion
	}
}
